package core.sim.aproxfunc;

import java.awt.Graphics2D;
import java.awt.geom.Point2D;

import graphics.*;
import stats.*;
import utility.*;
import core.*;
import core.genetic.*;
import core.neural.*;
import core.sim.*;

public class NeuralFunctionApproximation implements SingleSimulation {

	@Override
	public int getInfluencesCount() {
		return 1;
	}

	@Override
	public int getInputCounts() {
		return 1;
	}

	@Override
	public int getOutputCounts() {
		return 1;
	}

	@Override
	public int getSurroungingsCount() {
		return 1;
	}
	
	int sampleCount;

	public NeuralFunctionApproximation(int sampleCount) {
		this.sampleCount = sampleCount;
	}
	
	@Override
	public double[] playSimulation(Individual[] individuals) {

		int n = individuals.length;
		
		double[] res = new double[n];
		double[] values = new double[sampleCount];
		
		for(int i = 0;i<sampleCount;i++)
			values[i] = 1.0*i/(sampleCount-1);//Utils.random.nextDouble();
		
		for(int i = 0;i<n;i++) {
			res[i] = 0;
			for(int j = 0;j<sampleCount;j++) 
			{
				double x = values[j];
				
				//
				
				double freal = f(x);//IndividualBrain.sigmoid(12/(x*x*Math.cos(x)+1/x));
				//System.out.println(x + " " + frea);
				double findiv = Mode.mode.brain.calculateOutputs(individuals[i], new double[]{2*values[j]-1})[0];
				res[i] -= Math.sqrt((freal-findiv)*(freal-findiv));
			}
			Statistics.addTeamResult(res[i]);
		}		
		
		return res;
	}

	private double f(double x) {
		return (Math.cos(x*50)*Math.exp(-2.*x)+((x>0.2)?1:0)*Math.sin(10.*x))/3+0.5;
//		return Math.abs(x*Math.cos(10 * x * x));
	}
	
	@Override
	public void drawSimulation(Population pop, double[] values) {
		if ((Mode.mode.currentGeneration&16)==0) {
			synchronized (GraficPainter.drawMonitor) {
				int max = 0;
				for (int j = 1; j < values.length; j++)
					if (values[max] < values[j])
						max = j;

				MainApp.freal.clear();
				MainApp.findiv.clear();
				double[] vs = new double[sampleCount];

				for (int j = 0; j < sampleCount; j++)
					vs[j] = 1.0 * j / (sampleCount - 1);

				for (int j = 0; j < sampleCount; j++) {
					double x = vs[j];
					MainApp.freal.add(-f(x));
					MainApp.findiv.add(-Mode.mode.brain.calculateOutputs(pop.get(max), new double[] { 2*vs[j]-1 })[0]);
				}
//				MainApp.end = true;
			}
		}		
	}

	@Override
	public void drawMovie(Graphics2D g2, Point2D dim) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void executeForMovie(Individual[] individuals) {
		// TODO Auto-generated method stub
		
	}

}

